package emulator.unittest.hardware.nmos6502.timing;


import static org.junit.Assert.assertEquals;

import org.junit.Test;

import emulator.EmulatorException;
import emulator.hardware.nmos6502.Flags6502;

public class RelativeTest {

	@Test
	public void testBCC() throws EmulatorException
	{
		int opcode = 0x90;
		int flag = Flags6502.FLAG_CARRY;
		assertEquals(3, getCycles(opcode, 0, false));
		assertEquals(4, getCycles(opcode, 0, true));
		assertEquals(2, getCycles(opcode, flag, false));
		assertEquals(2, getCycles(opcode, flag, true));
	}
	
	@Test
	public void testBCS() throws EmulatorException
	{
		int opcode = 0xB0;
		int flag = Flags6502.FLAG_CARRY;
		assertEquals(2, getCycles(opcode, 0, false));
		assertEquals(2, getCycles(opcode, 0, true));
		assertEquals(3, getCycles(opcode, flag, false));
		assertEquals(4, getCycles(opcode, flag, true));
	}
	
	@Test
	public void testBVC() throws EmulatorException
	{
		int opcode = 0x50;
		int flag = Flags6502.FLAG_OVERFLOW;
		assertEquals(3, getCycles(opcode, 0, false));
		assertEquals(4, getCycles(opcode, 0, true));
		assertEquals(2, getCycles(opcode, flag, false));
		assertEquals(2, getCycles(opcode, flag, true));
	}
	
	@Test
	public void testBVS() throws EmulatorException
	{
		int opcode = 0x70;
		int flag = Flags6502.FLAG_OVERFLOW;
		assertEquals(2, getCycles(opcode, 0, false));
		assertEquals(2, getCycles(opcode, 0, true));
		assertEquals(3, getCycles(opcode, flag, false));
		assertEquals(4, getCycles(opcode, flag, true));
	}
	
	@Test
	public void testBPL() throws EmulatorException
	{
		int opcode = 0x10;
		int flag = Flags6502.FLAG_NEGATIVE;
		assertEquals(3, getCycles(opcode, 0, false));
		assertEquals(4, getCycles(opcode, 0, true));
		assertEquals(2, getCycles(opcode, flag, false));
		assertEquals(2, getCycles(opcode, flag, true));
	}
	
	@Test
	public void testBMI() throws EmulatorException
	{
		int opcode = 0x30;
		int flag = Flags6502.FLAG_NEGATIVE;
		assertEquals(2, getCycles(opcode, 0, false));
		assertEquals(2, getCycles(opcode, 0, true));
		assertEquals(3, getCycles(opcode, flag, false));
		assertEquals(4, getCycles(opcode, flag, true));
	}
	
	@Test
	public void testBNE() throws EmulatorException
	{
		int opcode = 0xD0;
		int flag = Flags6502.FLAG_ZERO;
		assertEquals(3, getCycles(opcode, 0, false));
		assertEquals(4, getCycles(opcode, 0, true));
		assertEquals(2, getCycles(opcode, flag, false));
		assertEquals(2, getCycles(opcode, flag, true));
	}
	
	@Test
	public void testBEQ() throws EmulatorException
	{
		int opcode = 0xF0;
		int flag = Flags6502.FLAG_ZERO;
		assertEquals(2, getCycles(opcode, 0, false));
		assertEquals(2, getCycles(opcode, 0, true));
		assertEquals(3, getCycles(opcode, flag, false));
		assertEquals(4, getCycles(opcode, flag, true));
	}
	
	private int getCycles(int opcode, int flags, boolean cross_page) throws EmulatorException
	{
		TimingTestBase test_base = new TimingTestBase();
		test_base.setRegisters(0, 0, 0, flags);
		test_base.setCommand((cross_page ? 0xF0 : 0), opcode, 0x70, 0);
		test_base.execute();
		return test_base.getElapsedCycles();
	}
}
